package com.sanbuTech.util;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.net.ssl.SSLContext;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

public class HttpRequestUtil {
    private static Logger logger = LoggerFactory.getLogger(HttpRequestUtil.class);    //日志记录
    private static String defalut_charset = "UTF-8";
 
    /**
     * httpPost
     * 
     * @param url  路径
     * @param paramsMap 参数
     * @return
     * @throws IOException 
     * @throws ClientProtocolException 
     */
    public static String httpPost(String url, Map<String, String> paramsMap) throws ClientProtocolException, IOException{
    	List<NameValuePair> params = new ArrayList<NameValuePair>();
    	
    	for(Map.Entry<String, String> entity : paramsMap.entrySet()){
    		params.add(new BasicNameValuePair(entity.getKey(), entity.getValue()));
    	}
    	CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        return post(httpclient, url, params);
    }
    
    /**
     * post json
     * @param url
     * @param paramsMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpPostJson(String url, Map<String, String> paramsMap) throws ClientProtocolException, IOException{
    	List<NameValuePair> params = new ArrayList<NameValuePair>();
    	String json = "{}";
    	
    	if(paramsMap != null && !paramsMap.isEmpty()){
    		json = JSONObject.toJSONString(paramsMap);
    	}
    	CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        return postJson(httpclient, url, json, defalut_charset);
    }
    
    /**
     * post json
     * @param url
     * @param paramsMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpPostJson(String url, String paramJson) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        return postJson(httpclient, url, paramJson, defalut_charset);
    }
    
    public static String httpPostJson(String url, String paramJson, Map<String, String> headerMap) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        return postJson(httpclient, url, paramJson, defalut_charset, headerMap);
    }
    
    /**
     * https加密链接 post请求
     * @param url
     * @param paramsMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpsPost(String url, Map<String, String> paramsMap) throws ClientProtocolException, IOException{
    	List<NameValuePair> params = new ArrayList<NameValuePair>();
    	
    	if(paramsMap != null && !paramsMap.isEmpty()){
    		for(Map.Entry<String, String> entity : paramsMap.entrySet()){
        		params.add(new BasicNameValuePair(entity.getKey(), entity.getValue()));
        	}
    	}
    	
    	CloseableHttpClient httpclient = createSSLClientDefault();
        return post(httpclient, url, params);
    }
    
    /**
     * https加密链接 post json
     * @param url
     * @param paramsMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpsPostJson(String url, Map<String, String> paramsMap) throws ClientProtocolException, IOException{
    	String json = "{}";
    	if(paramsMap != null && !paramsMap.isEmpty()){
    		json = JSONObject.toJSONString(paramsMap);
    	}
    	CloseableHttpClient httpclient = createSSLClientDefault();
        return postJson(httpclient, url, json, defalut_charset);
    }
    
    /**
     * https加密链接 post json
     * @param url
     * @param paramsMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpsPostJson(String url, String paramJson) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = createSSLClientDefault();
        return postJson(httpclient, url, paramJson, "UTF-8");
    }
    /**
     * https加密链接 post json
     * @param url
     * @param paramsMap
     * @param charset
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpsPostJson(String url, String paramJson, String charset) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = createSSLClientDefault();
        return postJson(httpclient, url, paramJson, charset);
    }
    
    protected static String postJson(CloseableHttpClient client, String url, String json, String charset) throws ClientProtocolException, IOException {
    	return postJson(client, url, json, charset, null);
	}
    
    protected static String postJson(CloseableHttpClient client, String url, String json, String charset, Map<String, String> headerMap) throws ClientProtocolException, IOException {
		if(StringUtils.isBlank(charset)){
			charset = defalut_charset;
		}
    	HttpPost post = new HttpPost(url);
		
		//Header拼装
		if(headerMap != null && headerMap.size() > 0){
			List<Header> headerList = new ArrayList<Header>();
			headerMap.forEach((key, value) ->{
				headerList.add(new BasicHeader(key, value));
			});
			post.setHeaders(headerList.toArray(new Header[]{}));
		}
		
//		ByteArrayEntity entity = new ByteArrayEntity(json.getBytes("UTF-8"), ContentType.APPLICATION_XML);

		StringEntity entity = new StringEntity(json, charset);
//		StringEntity entity = new StringEntity(new String(json.getBytes("UTF-8"), "ISO-8859-1"));
//		entity.setContentEncoding("gzip");
		entity.setContentType("application/json");
		
		post.setEntity(entity);
		CloseableHttpResponse response = client.execute(post);
//		String responseText = response.toString();
		HttpEntity responseEntity = response.getEntity();
		String jsonStr = EntityUtils.toString(responseEntity, Consts.UTF_8); //返回一般用UTF-8编码格式接受
		post.releaseConnection();
		return jsonStr;
	}
    
    
	protected static String post(CloseableHttpClient client, String url, List<NameValuePair> params) throws ClientProtocolException, IOException {
		HttpPost post = new HttpPost(url);
		HttpEntity entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
		post.setEntity(entity);
		CloseableHttpResponse response = client.execute(post);
//		String responseText = response.toString();
		HttpEntity responseEntity = response.getEntity();
		String jsonStr = EntityUtils.toString(responseEntity, "utf-8");
		post.releaseConnection();
		return jsonStr;
	}
	/*=======================POST End===============================*/
	
	/*=======================GET Start===============================*/
    /**
     * http GET 请求
     * @param url
     * @param paramsMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpGet(String url, Map<String, String> paramsMap) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        return get(httpclient, url, paramsMap);
    }
    
    /**
     * https加密链接 GET请求
     * @param url
     * @param paramsMap
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpsGet(String url, Map<String, String> paramsMap) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = createSSLClientDefault();
        return get(httpclient, url, paramsMap);
    }
	
	
    /**
     * http GET 请求
     * @param url
     * @param paramsStr
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpGet(String url, String paramsStr) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        return get(httpclient, url, paramsStr);
    }
    
    /**
     * https加密链接 GET请求
     * @param url
     * @param paramsStr
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String httpsGet(String url, String paramsStr) throws ClientProtocolException, IOException{
    	CloseableHttpClient httpclient = createSSLClientDefault();
        return get(httpclient, url, paramsStr);
    }
    
    
    protected static String get(CloseableHttpClient client, String url, String paramsStr) throws ClientProtocolException, IOException {
    	if(!StringUtils.isBlank(paramsStr)){
    		url += "?" + paramsStr;
    	}
    	
		HttpGet get = new HttpGet(url);
		
		CloseableHttpResponse response = client.execute(get);
//		String responseText = response.toString();
		HttpEntity responseEntity = response.getEntity();
		String jsonStr = EntityUtils.toString(responseEntity, "utf-8");
		get.releaseConnection();
		return jsonStr;
	}
    
    protected static String get(CloseableHttpClient client, String url, Map<String, String> paramsMap) throws ClientProtocolException, IOException {
    	if(paramsMap != null && !paramsMap.isEmpty()){
    		url += "?";
    		for(Entry<String, String> entry : paramsMap.entrySet()){
    			url += entry.getKey() + "=" + entry.getValue() + "&";
    		};
    	}
    	
		HttpGet get = new HttpGet(url);
		
		CloseableHttpResponse response = client.execute(get);
//		String responseText = response.toString();
		HttpEntity responseEntity = response.getEntity();
		String jsonStr = EntityUtils.toString(responseEntity, "utf-8");
		get.releaseConnection();
		return jsonStr;
	}
    
	/**
	 * 创造ssl加密的httpclient对象
	 * @return
	 */
	@SuppressWarnings("deprecation")
	protected static CloseableHttpClient createSSLClientDefault(){
		try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				@Override
				public boolean isTrusted(X509Certificate[] chain,
						String authType) throws CertificateException {
					//信任所有, 也就是不需要证书验证
					return true;
				}
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            		sslContext,
            		//允许所有host, 否则报错 Host name 'xxxx' does not match the certificate subject provided by the peer, 
            		//懒得去搞store证书, 方便可以查询所有链接
            		SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
            		);
			return HttpClients
					.custom()
					.setSSLSocketFactory(sslsf)
					.build();
            
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            e.printStackTrace();
        } 
        return HttpClients.createDefault();
	}

	public static void main(String[] args) throws ClientProtocolException, IOException {
//		String url = "http://bearo.ufile.ucloud.cn/";
//		String url = "http://localhost/payCenterController/upload";
//		String responseText = HttpRequestUtil.httpPost(url, new HashMap<String, String>());
//		System.out.println(responseText);
		
		String urls = "https://localhost:8443/sexmaster/login/test";
		Map<String, String> paramsMap = new HashMap<String, String>();
//		appid, String sign, String data
		paramsMap.put("hehe", "hehevalue");
		String jsonStr = httpsGet(urls, paramsMap);
		System.err.println(jsonStr);
	}
    
}